package com.yycx.app.provider.integration.provider;


import com.yycx.app.provider.service.impl.AppUserDetailsService;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.constants.CommonConstants;
import com.yycx.common.enums.AccountTypeEnum;
import com.yycx.common.security.OpenUser;
import com.yycx.common.security.passwordencoder.Md5PasswordEncoder;
import com.yycx.common.utils.WebUtils;
import com.yycx.module.user.client.entity.AppAccount;
import com.yycx.module.user.provider.service.AppAccountService;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collection;

/**
 * 实现自己的AuthenticationProvider类，用来自定义用户校验机制
 *
 * @author zyf
 * @date 2018/9/5
 */
@Component
public class AppAuthenticationProvider implements AuthenticationProvider {

    @Resource
    private AppUserDetailsService customerDetailService;

    @Resource
    private AppAccountService appAccountService;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 获取表单输入中返回的用户名;
        String userName = (String) authentication.getPrincipal();
        // 获取表单中输入的密码；
        String password = (String) authentication.getCredentials();
        // 获取登录类型
        String accountType = WebUtils.getHttpServletRequest().getParameter("accountType");
        //如果密码长度大于6则说明是用密码模式登录
        if(FlymeUtils.isNotEmpty(password)&&password.length()>6){
            accountType= AccountTypeEnum.USERNAME.name();
        }
        String userType = WebUtils.getHttpServletRequest().getParameter("userType");
        String clientId = WebUtils.getHttpServletRequest().getParameter("client_id");
        // 这里调用我们的自己写的获取用户的方法；
        OpenUser userInfo = (OpenUser) customerDetailService.loadUserByUsername(userName);
        if (userInfo == null) {
            throw new BadCredentialsException("用户名不存在");
        }
        userInfo.setClientId(clientId);
        //排除不验证密码的登录类型
        if (!CommonConstants.NO_AUTH_TYPE.contains(accountType)) {
            // 这里我们还要判断密码是否正确，这里我们的密码使用PasswordEncoder进行加密的
            if (passwordEncoder instanceof Md5PasswordEncoder) {
                Long accountId = userInfo.getAccountId();
                AppAccount appAccount = appAccountService.getById(accountId);
                String md5Salt = appAccount.getMd5Salt();
                String account = appAccount.getAccount();
                Md5PasswordEncoder md5PasswordEncoder = (Md5PasswordEncoder) passwordEncoder;
                md5PasswordEncoder.setSalt(md5Salt);
                md5PasswordEncoder.setAccount(account);
            }
            if (!passwordEncoder.matches(password, userInfo.getPassword())) {
                throw new BadCredentialsException("密码不正确");
            }
        }
        // 这里还可以加一些其他信息的判断，比如用户账号已停用等判断。
        Collection<? extends GrantedAuthority> authorities = userInfo.getAuthorities();
        // 构建返回的用户登录成功的token
        return new UsernamePasswordAuthenticationToken(userInfo, password, authorities);
    }

    @Override
    public boolean supports(Class<?> authentication) {
//      这里直接改成retrun true;表示是支持这个执行
        return true;
    }
}